/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004-2005  Benoit Blanchon                      */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/


/******************************************************************/
/* Includes                                                       */
/******************************************************************/

// module's interface
#include "Config.h"

// project's headers
#include "Assert.h"
#include "Version.h"

// standard headers
#include <tchar.h>


/******************************************************************/
/* Internal data types                                            */
/******************************************************************/

typedef struct {
  LPCTSTR	szName ;
  LPTSTR	szValue ;
} CONFIG_STRING ;

typedef struct {
  LPCTSTR	szName ;
  int		iValue ;
} CONFIG_INTEGER ;


/******************************************************************/
/* Internal constants                                             */
/******************************************************************/

#define CONFIG_STRING_MAX	256

static LPCTSTR szRegKey = TEXT("Software\\" APPLICATION_NAME) ;


/******************************************************************/
/* Internal data                                                  */
/******************************************************************/

static CONFIG_STRING aStrings[_CFGSTR_COUNT] = {
  { TEXT("Language"),	NULL }
} ;

static CONFIG_INTEGER aIntegers[_CFGINT_COUNT] = {
  { TEXT("Check for updates"),		1 },
  { TEXT("Enable Poochy picture"),	1 },
  { TEXT("Enable sound"),		1 },
  { TEXT("Max log file size"),		8192 }
} ;


/******************************************************************/
/* Exported function : Init                                       */
/******************************************************************/

BOOL Config_Init () 
{
  HKEY		hkey ;
  DWORD		dwSize ;
  DWORD		dwType ;
  DWORD		dwValue ;
  LONG		lResult ;
  TCHAR		szBuffer[CONFIG_STRING_MAX] ;
  int		i ;
  
  // try to create config on LOCAL_MACHINE root key
  lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0, 
			    TEXT(""), REG_OPTION_NON_VOLATILE, 
			    KEY_QUERY_VALUE, NULL, &hkey, NULL) ;

  // else try in CURRENT_USER
  if( lResult!=ERROR_SUCCESS )
    lResult = RegCreateKeyEx (HKEY_CURRENT_USER, szRegKey, 0, 
			      TEXT(""), REG_OPTION_NON_VOLATILE, 
			      KEY_QUERY_VALUE, NULL, &hkey, NULL) ;

  // if both failed the surrender
  if( lResult!=ERROR_SUCCESS )
    return FALSE ;
  
  // for each config string (begin)
  for( i=0 ; i<_CFGSTR_COUNT ; i++ )
    {
      // get value
      dwSize = CONFIG_STRING_MAX ;
      dwType = REG_SZ ;      
      lResult = RegQueryValueEx (hkey, aStrings[i].szName, NULL, 			
				 &dwType, (BYTE*)szBuffer, &dwSize) ;
      // if success then store value
      if( lResult==ERROR_SUCCESS && szBuffer[0]!=0 )
	aStrings[i].szValue = _tcsdup (szBuffer) ;    
    }
  // for each config string (end)

  // for each config integer (begin)
  for( i=0 ; i<_CFGINT_COUNT ; i++ )
    {
      // get value
      dwSize = sizeof(DWORD) ;
      dwType = REG_DWORD ;
      lResult = RegQueryValueEx (hkey, aIntegers[i].szName, NULL, 
				 &dwType, (BYTE*)&dwValue, &dwSize) ;
      // if success then store value
      if( lResult==ERROR_SUCCESS )
	aIntegers[i].iValue = dwValue ;
    }
  // for each config integer (end)

  RegCloseKey (hkey) ;
 
  return TRUE ;
}


/******************************************************************/
/* Exported function : Uninit                                     */
/******************************************************************/

BOOL Config_Uninit ()
{
  return Config_Save () ;
}


/******************************************************************/
/* Exported function : Save                                       */
/******************************************************************/

BOOL Config_Save ()
{
  HKEY		hkey ;
  DWORD		dwValue ;
  LONG		lResult ;
  int		i ;

  // try to create config on LOCAL_MACHINE root key
  lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0,
			    TEXT(""), REG_OPTION_NON_VOLATILE, 
			    KEY_SET_VALUE, NULL, &hkey, NULL) ;

  // else try in CURRENT_USER
  if( lResult!=ERROR_SUCCESS )
    lResult = RegCreateKeyEx (HKEY_CURRENT_USER, szRegKey, 0, 
			      TEXT(""), REG_OPTION_NON_VOLATILE, 
			      KEY_SET_VALUE, NULL, &hkey, NULL) ;
  
  // if both failed then surrender
  if( lResult!=ERROR_SUCCESS )
    return FALSE ;

  // for each config string (begin)
  for( i=0 ; i<_CFGSTR_COUNT ; i++ )
    {
      if( aStrings[i].szValue ) {
	RegSetValueEx (hkey, aStrings[i].szName, 0, REG_SZ, 
		       (BYTE*)aStrings[i].szValue, 
		       (_tcslen(aStrings[i].szValue)+1)*sizeof(TCHAR)) ; 
	free (aStrings[i].szValue) ;
	aStrings[i].szValue = NULL ;	
      }
      else
	RegSetValueEx (hkey, aStrings[i].szName, 0, REG_SZ, (BYTE*)TEXT(""), 2*sizeof(TCHAR)) ; 
    }
  // for each config string (end)
  
  // for each config integer (begin)
  for( i=0 ; i<_CFGINT_COUNT ; i++ )
    {
      dwValue = aIntegers[i].iValue ;
      RegSetValueEx (hkey, aIntegers[i].szName, 0, REG_DWORD, 
		     (BYTE*)&dwValue, sizeof(dwValue)) ; 
    }
  // for each config integer (end)
      
  RegCloseKey (hkey) ;

  return TRUE ;
}


/******************************************************************/
/* Exported function : GetInteger                                 */
/******************************************************************/

int Config_GetInteger (CONFIG_INTEGER_ID id)
{
  ASSERT (id>=0) ;
  ASSERT (id<_CFGINT_COUNT) ;

  return aIntegers[id].iValue ;
}


/******************************************************************/
/* Exported function : SetInteger                                 */
/******************************************************************/

void Config_SetInteger (CONFIG_INTEGER_ID id, int iValue)
{
  ASSERT (id>=0) ;
  ASSERT (id<_CFGINT_COUNT) ;

  aIntegers[id].iValue = iValue ;
}


/******************************************************************/
/* Exported function : GetString                                  */
/******************************************************************/

LPCTSTR Config_GetString (CONFIG_STRING_ID id)
{
  ASSERT (id>=0) ;
  ASSERT (id<_CFGSTR_COUNT) ;

  return aStrings[id].szValue ;
}


/******************************************************************/
/* Exported function : SetString                                  */
/******************************************************************/

void Config_SetString (CONFIG_STRING_ID id, LPCTSTR szValue)
{
  ASSERT (id>=0) ;
  ASSERT (id<_CFGSTR_COUNT) ;

  free (aStrings[id].szValue) ;
  aStrings[id].szValue = _tcsdup (szValue) ;
}
